/*
 *   Copyright 2008 Francois Fernandes
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */
package com.googlecode.opendoclibrary.connector.internal.jms;

import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

public class ConnectionManager
{

    protected static class OlderThanIterator implements Iterator<String>
    {
        private Iterator<Map.Entry<String, State>> iter;

        private Map.Entry<String, State> next;

        private long timestamp;

        public OlderThanIterator( Iterator<Map.Entry<String, State>> iter, long timestamp )
        {
            super();
            this.iter = iter;
            this.timestamp = timestamp;
        }

        @Override
        public boolean hasNext()
        {
            return nextEntry() != null;
        }

        @Override
        public String next()
        {
            Map.Entry<String, State> entry = nextEntry();
            if ( entry == null )
            {
                throw new NoSuchElementException();
            }
            next = null;
            return entry.getKey();
        }

        protected Map.Entry<String, State> nextEntry()
        {
            if ( next == null )
            {
                while ( iter.hasNext() && next == null )
                {
                    Map.Entry<String, State> tmp = iter.next();

                    if ( tmp.getValue().getUpdateTimestamp() < timestamp )
                    {
                        next = tmp;
                    }
                }
            }

            return next;
        }

        @Override
        public void remove()
        {
            if ( next == null )
            {
                throw new IllegalStateException( "next has not been called or no more elements are available" );
            }
            iter.remove();
        }
    }

    protected static class State
    {
        private final long creationTimestamp;

        private long updateTimestamp;

        public State( long creationTimestamp )
        {
            super();
            this.creationTimestamp = creationTimestamp;
            updateTimestamp = creationTimestamp;
        }

        public long getCreationTimestamp()
        {
            return creationTimestamp;
        }

        public long getUpdateTimestamp()
        {
            return updateTimestamp;
        }

        public void update()
        {
            updateTimestamp = System.currentTimeMillis();
        }
    }

    private ConcurrentHashMap<String, State> states;

    public ConnectionManager()
    {
        states = new ConcurrentHashMap<String, State>();
    }

    public String createConnectionId()
    {
        String connectionId = UUID.randomUUID().toString();
        states.put( connectionId, new State( System.currentTimeMillis() ) );
        return connectionId;
    }

    public long getCreationTimestamp( String connectionId )
    {
        return getState( connectionId ).getCreationTimestamp();
    }

    private State getState( String connectionId )
    {
        State s = states.get( connectionId );
        if ( s == null )
        {
            throw new IllegalArgumentException( "no state for " + connectionId );
        }
        return s;
    }

    public long getUpdateTimestamp( String connectionId )
    {
        return getState( connectionId ).getUpdateTimestamp();
    }

    public Iterator<String> iterateOverOlderThan( int i )
    {
        return null;
    }

    public void update( String connectionId )
    {
        getState( connectionId ).update();
    }

}
